package com.todo.member.application.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.todo.common.common.entity.response.page.PageResult;
import com.todo.common.common.enums.BizErrorCodeEnum;
import com.todo.common.common.exception.BizException;
import com.todo.common.utils.StringUtils;
import com.todo.component.redis.RedisService;
import com.todo.member.application.convert.TaskConvert;
import com.todo.member.application.entity.bo.MemberTaskBO;
import com.todo.member.application.entity.condition.MemberTaskConditionBO;
import com.todo.member.application.service.MemberTaskService;
import com.todo.member.common.base.redis.TaskKeyBuild;
import com.todo.member.common.enums.MemberTaskStatusEnum;
import com.todo.member.infrastructure.entity.condition.MemberTaskCondition;
import com.todo.member.infrastructure.entity.po.MemberTaskPO;
import com.todo.member.infrastructure.repository.MemberTaskRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author azhebuxing
 * @date 2025/3/5 02:14
 * @description
 */
@Slf4j
@Service
public class MemberTaskServiceImpl implements MemberTaskService {

    @Resource
    private MemberTaskRepository memberTaskRepository;
    @Resource
    private RedisService redisService;

    @Override
    public Boolean insertMemberTask(MemberTaskBO memberTaskBO) {
        if (memberTaskBO == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "数据为空");
        }
        if (memberTaskBO.getStartTime().after(memberTaskBO.getEndTime())) {
            log.error("MemberTaskService#insertMemberTask 创建任务失败，活动时间数据异常，开始时间在结束时间之后 memberTaskBO：【{}】", JSONObject.toJSONString(memberTaskBO));
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "活动时间数据异常");
        }
        Date now = new Date();
        if (memberTaskBO.getStartTime().after(now)) {
            log.error("MemberTaskService#insertMemberTask 创建任务失败，活动时间数据异常，开始时间在当前时间之后，不允许新增 memberTaskBO：【{}】", JSONObject.toJSONString(memberTaskBO));
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "活动时间数据异常");
        }
        //TODO 规则逻辑可用判断 memberTaskBO.getRewardCalLogic();memberTaskBO.getFinishRule()

        MemberTaskPO memberTaskPO = memberTaskRepository.queryMemberTaskPOByTitle(memberTaskBO.getTitle());
        if (memberTaskPO != null) {
            log.error("MemberTaskService#insertMemberTask 创建任务失败，任务名称重复 memberTaskBO：【{}】", JSONObject.toJSONString(memberTaskBO));
            throw new BizException(BizErrorCodeEnum.OPERATION_FAILED, "任务名称重复");
        }
        MemberTaskPO insertData = TaskConvert.convertToMemberTaskPO(memberTaskBO);
        Boolean insertResult = memberTaskRepository.insertMemberTaskPO(insertData);
        if (insertResult) {
            String taskInfoKey = TaskKeyBuild.buildTaskInfoKey(insertData.getId());
            redisService.setOneDay(taskInfoKey, JSONObject.toJSONString(memberTaskBO));
        }
        return insertResult;
    }

    @Override
    public Boolean updateMemberTask(MemberTaskBO memberTaskBO) {
        if (memberTaskBO == null || memberTaskBO.getId() == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "数据为空");
        }
        if (memberTaskBO.getStartTime().after(memberTaskBO.getEndTime())) {
            log.error("MemberTaskService#updateMemberTask 更新任务失败，活动时间数据异常，开始时间在结束时间之后 memberTaskBO：【{}】", JSONObject.toJSONString(memberTaskBO));
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "活动时间数据异常");
        }
        Date now = new Date();
        if (memberTaskBO.getStartTime().after(now)) {
            log.error("MemberTaskService#updateMemberTask 更新任务失败，活动时间数据异常，开始时间在当前时间之后，不允许新增 memberTaskBO：【{}】", JSONObject.toJSONString(memberTaskBO));
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "活动时间数据异常");
        }
        //TODO 规则逻辑可用判断 memberTaskBO.getRewardCalLogic();memberTaskBO.getFinishRule()

        MemberTaskBO alreadyData = queryMemberTaskById(memberTaskBO.getId());
        if (alreadyData == null) {
            log.error("MemberTaskService#updateMemberTask 更新任务失败，任务不存在 memberTaskBO：【{}】", JSONObject.toJSONString(memberTaskBO));
            throw new BizException(BizErrorCodeEnum.OPERATION_FAILED, "任务不存在");
        }
        //标题是否重复
        if (!alreadyData.getTitle().equals(memberTaskBO.getTitle())) {
            MemberTaskPO memberTaskPO = memberTaskRepository.queryMemberTaskPOByTitle(memberTaskBO.getTitle());
            if (memberTaskPO != null) {
                log.error("MemberTaskService#updateMemberTask 更新任务失败，任务名称重复 memberTaskBO：【{}】", JSONObject.toJSONString(memberTaskBO));
                throw new BizException(BizErrorCodeEnum.OPERATION_FAILED, "任务名称重复");
            }
        }

        memberTaskBO.setStatus(MemberTaskStatusEnum.DRAFT);
        MemberTaskPO memberTaskPO = TaskConvert.convertToMemberTaskPO(memberTaskBO);
        Boolean updated = memberTaskRepository.updateMemberTaskPOById(memberTaskPO);
        if (updated) {
            String taskInfoKey = TaskKeyBuild.buildTaskInfoKey(memberTaskPO.getId());
            redisService.del(taskInfoKey);
        }
        return updated;
    }

    @Override
    public Boolean removeMemberTaskById(Long id) {
        if (id == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "数据为空");
        }
        MemberTaskBO memberTaskBO = queryMemberTaskById(id);
        if (memberTaskBO == null) {
            return true;
        }
        if (memberTaskBO.getStatus().equals(MemberTaskStatusEnum.EFFECTIVE)) {
            log.error("MemberTaskService#removeMemberTaskById 删除任务失败，任务状态为生效中，不允许删除 memberTaskBO：【{}】", JSONObject.toJSONString(memberTaskBO));
            throw new BizException(BizErrorCodeEnum.OPERATION_FAILED, "任务状态为生效中，不允许删除");
        }
        Boolean removed = memberTaskRepository.removeMemberTaskPOById(id);
        if (removed) {
            String taskInfoKey = TaskKeyBuild.buildTaskInfoKey(id);
            redisService.del(taskInfoKey);
            //如果是生效中的任务，需要删除redis缓存【其实不存在，生效中的无法删除】
            if (memberTaskBO.getStatus().equals(MemberTaskStatusEnum.EFFECTIVE)) {
                String effectiveTaskListKey = TaskKeyBuild.buildEffectiveTaskListKey();
                redisService.hDel(effectiveTaskListKey, String.valueOf(id));
            }

        }
        return removed;
    }

    @Override
    public MemberTaskBO queryMemberTaskById(Long id) {
        if (id == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "数据为空");
        }
        String cacheValue = redisService.get(TaskKeyBuild.buildTaskInfoKey(id));
        if (StringUtils.isNotEmpty(cacheValue)) {
            return JSONObject.parseObject(cacheValue, MemberTaskBO.class);
        }
        MemberTaskPO memberTaskPO = memberTaskRepository.queryMemberTaskPOById(id);
        MemberTaskBO memberTaskBO = TaskConvert.convertToMemberTaskBO(memberTaskPO);
        if (memberTaskBO != null) {
            redisService.setOneDay(TaskKeyBuild.buildTaskInfoKey(id), JSONObject.toJSONString(memberTaskBO));
            return memberTaskBO;
        }
        return memberTaskBO;
    }

    @Override
    public Boolean updateMemberTaskStatusById(Long id, MemberTaskStatusEnum oldStatus, MemberTaskStatusEnum newStatus) {
        if (id == null || oldStatus == null || newStatus == null) {
            return false;
        }
        MemberTaskBO memberTaskBO = queryMemberTaskById(id);
        if (memberTaskBO == null) {
            log.error("MemberTaskService#updateMemberTaskStatusById 更新任务状态失败，任务不存在 memberTaskBO：【{}】", JSONObject.toJSONString(memberTaskBO));
            return false;
        }
        if (memberTaskBO.getStatus().equals(newStatus)) {
            return true;
        }
        Boolean updated = memberTaskRepository.updateMemberTaskStatusById(id, oldStatus, newStatus);
        if (updated) {
            redisService.del(TaskKeyBuild.buildTaskInfoKey(id));
            if (newStatus.equals(MemberTaskStatusEnum.EFFECTIVE)) {
                String effectiveTaskListKey = TaskKeyBuild.buildEffectiveTaskListKey();
                redisService.hSet(effectiveTaskListKey, String.valueOf(id), JSONObject.toJSONString(memberTaskBO));
            }
            if (oldStatus.equals(MemberTaskStatusEnum.EFFECTIVE)) {
                String effectiveTaskListKey = TaskKeyBuild.buildEffectiveTaskListKey();
                redisService.hDel(effectiveTaskListKey, String.valueOf(id));
            }
        }
        return updated;
    }

    @Override
    public PageResult<MemberTaskBO> queryMemberTaskByPage(MemberTaskConditionBO memberTaskConditionBO) {
        if (memberTaskConditionBO == null) {
            return PageResult.of(Collections.emptyList(), memberTaskConditionBO.getPageNum(), memberTaskConditionBO.getPageSize(), 0);
        }
        MemberTaskCondition memberTaskCondition = TaskConvert.convertToMemberTaskCondition(memberTaskConditionBO);
        PageResult<MemberTaskPO> pageResult = memberTaskRepository.queryMemberTaskPOByPage(memberTaskCondition);
        return TaskConvert.convertToMemberTaskPageResult(pageResult);
    }

    @Override
    public List<MemberTaskBO> queryEffectiveMemberTaskList() {
        Map<String, String> stringStringMap = redisService.hGetAll(TaskKeyBuild.buildEffectiveTaskListKey());
        if (MapUtils.isNotEmpty(stringStringMap)) {
            List<MemberTaskBO> memberTaskBOList = Lists.newArrayList();
            for (String key : stringStringMap.keySet()) {
                MemberTaskBO memberTaskBO = JSONObject.parseObject(stringStringMap.get(key), MemberTaskBO.class);
                memberTaskBOList.add(memberTaskBO);
            }
            return memberTaskBOList;
        }
        return Collections.emptyList();
    }
}
